home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EuroCD 3
/
EuroCD 3.iso
/
Programming
/
PPCbwb111
/
source
/
bwb_ops.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-24
|
56KB
|
2,182 lines
/****************************************************************
bwb_ops.c Expression Parsing Operations
for Bywater BASIC Interpreter
Copyright (c) 1992, Ted A. Campbell
Bywater Software
P. O. Box 4023
Duke Station
Durham, NC 27706
email: tcamp@acpub.duke.edu
Copyright and Permissions Information:
All U.S. and international copyrights are claimed by the
author. The author grants permission to use this code
and software based on it under the following conditions:
(a) in general, the code and software based upon it may be
used by individuals and by non-profit organizations; (b) it
may also be utilized by governmental agencies in any country,
with the exception of military agencies; (c) the code and/or
software based upon it may not be sold for a profit without
an explicit and specific permission from the author, except
that a minimal fee may be charged for media on which it is
copied, and for copying and handling; (d) the code must be
distributed in the form in which it has been released by the
author; and (e) the code and software based upon it may not
be used for illegal activities.
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "bwbasic.h"
#include "bwb_mes.h"
/* declarations for functions visible in this file only */
static int op_oplevel( int level );
static int op_add( int level, int precision );
static int op_subtract( int level, int precision );
static int op_multiply( int level, int precision );
static int op_divide( int level, int precision );
static int op_assign( int level, int precision );
static int op_equals( int level, int precision );
static int op_lessthan( int level, int precision );
static int op_greaterthan( int level, int precision );
static int op_lteq( int level, int precision );
static int op_gteq( int level, int precision );
static int op_notequal( int level, int precision );
static int op_modulus( int level, int precision );
static int op_exponent( int level, int precision );
static int op_intdiv( int level, int precision );
static int op_or( int level, int precision );
static int op_and( int level, int precision );
static int op_not( int level, int precision );
static int op_xor( int level, int precision );
static int op_islevelstr( int level );
static int op_getprecision( int level );
static int op_isoperator( int operation );
static int op_pulldown( int how_far );
static int op_level;
/***************************************************************
FUNCTION: exp_operation()
DESCRIPTION: This function performs whatever operations
are necessary at the end of function bwb_exp.
***************************************************************/
int
exp_operation( int entry_level )
{
register int precedence;
int operator;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_operation(): entered function." );
bwb_debug( bwb_ebuf );
#endif
/* cycle through all levels of precedence and perform required
operations */
for ( precedence = 0; precedence <= MAX_PRECEDENCE; ++precedence )
{
/* Operation loop: cycle through every level above entry level
and perform required operations as needed */
op_level = entry_level + 1;
while( ( op_level < exp_esc )
&& ( op_isoperator( exp_es[ op_level ].operation ) == FALSE ))
{
++op_level;
}
while ( ( op_level > entry_level ) && ( op_level < exp_esc ) )
{
/* see if the operation at this level is an operator with the
appropriate precedence level by running through the table
of operators */
for ( operator = 0; operator < N_OPERATORS; ++operator )
{
if ( exp_ops[ operator ].operation == exp_es[ op_level ].operation )
{
/* check for appropriate level of precedence */
if ( exp_ops[ operator ].precedence == precedence )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_operation(): level <%d> operation <%d>",
op_level, exp_es[ op_level ].operation );
bwb_debug( bwb_ebuf );
#endif
op_oplevel( op_level ); /* perform the operation */
}
}
}
/* advance level if appropriate; one must check, however, since
the op_oplevel() function may have decremented exp_esc */
if ( op_level < exp_esc )
{
++op_level;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_operation() first increment op_level to <%d>",
op_level );
bwb_debug( bwb_ebuf );
#endif
while ( ( op_isoperator( exp_es [ op_level ].operation ) == FALSE )
&& ( op_level < exp_esc ) )
{
++op_level;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in exp_operation() further increment op_level to <%d>",
op_level );
bwb_debug( bwb_ebuf );
#endif
}
} /* end of increment of op_level */
} /* end of for loop for stack levels */
} /* end of for loop for precedence levels */
return TRUE;
} /* end of function exp_operation() */
/***************************************************************
FUNCTION: op_oplevel()
DESCRIPTION: This function performs a specific operation
at a specific level.
***************************************************************/
static int
op_oplevel( int level )
{
int precision;
/* set the precision */
if ( ( precision = op_getprecision( level ) ) == OP_ERROR )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "exp_operation(): failed to set precision." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch ); /*** ??? ***/
#endif
op_pulldown( 2 );
}
/* precision is set correctly */
else
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_oplevel(): level <%d>, precision <%c>",
level, precision );
bwb_debug( bwb_ebuf );
#endif
switch ( exp_es[ level ].operation )
{
case OP_ADD:
op_add( level, precision );
break;
case OP_SUBTRACT:
op_subtract( level, precision );
break;
case OP_MULTIPLY:
op_multiply( level, precision );
break;
case OP_DIVIDE:
op_divide( level, precision );
break;
case OP_ASSIGN:
op_assign( level, precision );
break;
case OP_EQUALS:
op_equals( level, precision );
break;
case OP_LESSTHAN:
op_lessthan( level, precision );
break;
case OP_GREATERTHAN:
op_greaterthan( level, precision );
break;
case OP_LTEQ:
op_lteq( level, precision );
break;
case OP_GTEQ:
op_gteq( level, precision );
break;
case OP_NOTEQUAL:
op_notequal( level, precision );
break;
case OP_MODULUS:
op_modulus( level, precision );
break;
case OP_INTDIVISION:
op_intdiv( level, precision );
break;
case OP_OR:
op_or( level, precision );
break;
case OP_AND:
op_and( level, precision );
break;
case OP_NOT:
op_not( level, precision );
break;
case OP_XOR:
op_xor( level, precision );
break;
case OP_EXPONENT:
op_exponent( level, precision );
break;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported." );
op_pulldown( 2 );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
break;
} /* end of case statement for operators */
} /* end of else statement, precision set */
return TRUE;
} /* end of function op_oplevel() */
/***************************************************************
FUNCTION: op_isoperator()
DESCRIPTION: This function detects whether its argument
is an operator.
***************************************************************/
static int
op_isoperator( int operation )
{
register int c;
for( c = 0; c < N_OPERATORS; ++c )
{
if ( operation == exp_ops[ c ].operation )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_isoperator(): found match <%s>",
exp_ops[ c ].symbol );
bwb_debug( bwb_ebuf );
#endif
return TRUE;
}
}
/* test failed; return FALSE */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_isoperator(): no match found for operation <%d>",
operation );
bwb_debug( bwb_ebuf );
#endif
return FALSE;
}
/***************************************************************
FUNCTION: op_add()
DESCRIPTION: This function adds two numbers or
concatenates two strings.
***************************************************************/
static int
op_add( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be strings for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in op_add(): Type mismatch in string addition." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* concatenate the two strings */
if ( error_condition == FALSE )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:",
level - 1, exp_es[ level - 1 ].operation, exp_es[ level - 1 ].type );
bwb_debug( bwb_ebuf );
exp_getsval( &( exp_es[ level - 1 ] ));
sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:",
level + 1, exp_es[ level + 1 ].operation, exp_es[ level + 1 ].type );
bwb_debug( bwb_ebuf );
exp_getsval( &( exp_es[ level + 1 ] ));
sprintf( bwb_ebuf, "in op_add(): string addition, exp_getsval()s completed" );
bwb_debug( bwb_ebuf );
#endif
str_cat( exp_getsval( &( exp_es[ level - 1 ] ) ),
exp_getsval( &( exp_es[ level + 1 ] ) ) );
}
exp_es[ level - 1 ].operation = CONST_STRING;
break;
case DOUBLE:
exp_es[ level - 1 ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
+ exp_getdval( &( exp_es[ level + 1 ] ));
exp_es[ level - 1 ].operation = NUMBER;
break;
case SINGLE:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add(): single, (level <%d>) <%f> + <%f> (level <%d>",
level - 1, exp_getfval( &( exp_es[ level - 1 ] )),
exp_getfval( &( exp_es[ level + 1 ] )), level + 1 );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level - 1 ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
+ exp_getfval( &( exp_es[ level + 1 ] ));
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add(): single, = <%f>",
exp_es[ level - 1 ].fval );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level - 1 ].operation = NUMBER;
break;
case INTEGER:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add(): Integer precision." );
bwb_debug ( bwb_ebuf );
sprintf( bwb_ebuf, "in op_add(): precisions: lhs <%d> rhs <%d>.",
exp_es[ level - 1 ].type,
exp_es[ level + 1 ].type );
bwb_debug ( bwb_ebuf );
#endif
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
+ exp_getival( &( exp_es[ level + 1 ] ));
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add(): integer addition, result is <%d>",
exp_es[ level - 1 ].ival );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level - 1 ].operation = NUMBER;
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_add() returns with operation <%d> type <%c>",
exp_es[ level - 1 ].operation, exp_es[ level - 1 ].type );
bwb_debug( bwb_ebuf );
#endif
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_subtract()
DESCRIPTION: This function subtracts the number on
the left from the number on the right.
***************************************************************/
static int
op_subtract( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be subtracted." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
- exp_getdval( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_subtract(): Single precision." );
bwb_debug ( bwb_ebuf );
sprintf( bwb_ebuf, "in op_subtract(): precisions: lhs <%d> rhs <%d>.",
exp_es[ level - 1 ].type,
exp_es[ level + 1 ].type );
bwb_debug ( bwb_ebuf );
sprintf( bwb_ebuf, "in op_subtract(): values: lhs <%f> rhs <%f>.",
exp_getfval( &( exp_es[ level - 1 ] )),
exp_getfval( &( exp_es[ level + 1 ] )) );
bwb_debug ( bwb_ebuf );
#endif
exp_es[ level - 1 ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
- exp_getfval( &( exp_es[ level + 1 ] ));
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_subtract(): SINGLE subtraction, result is <%f>",
exp_es[ level - 1 ].fval );
bwb_debug( bwb_ebuf );
#endif
break;
case INTEGER:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_subtract(): Integer precision." );
bwb_debug ( bwb_ebuf );
sprintf( bwb_ebuf, "in op_subtract(): precisions: lhs <%d> rhs <%d>.",
exp_es[ level - 1 ].type,
exp_es[ level + 1 ].type );
bwb_debug ( bwb_ebuf );
#endif
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
- exp_getival( &( exp_es[ level + 1 ] ));
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_subtract(): integer subtraction, result is <%d>",
exp_es[ level - 1 ].ival );
bwb_debug( bwb_ebuf );
#endif
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_multiply()
DESCRIPTION: This function multiplies the number on
the left from the number on the right.
***************************************************************/
static int
op_multiply( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be multiplied." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
* exp_getdval( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
exp_es[ level - 1 ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
* exp_getfval( &( exp_es[ level + 1 ] ));
break;
case INTEGER:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
* exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_divide()
DESCRIPTION: This function divides the number on
the left by the number on the right.
***************************************************************/
static int
op_divide( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be divided." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level + 1 ] ))
== 0.0 )
{
exp_es[ level - 1 ].dval = -1.0;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level - 1 ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
/ exp_getdval( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level + 1 ] ))
== (float) 0.0 )
{
exp_es[ level - 1 ].fval = (float) -1.0;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level - 1 ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
/ exp_getfval( &( exp_es[ level + 1 ] ));
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level + 1 ] ))
== 0 )
{
exp_es[ level - 1 ].ival = -1;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
/ exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_assign()
DESCRIPTION: This function assigns the value in the
right hand side to the variable in the left hand side.
***************************************************************/
static int
op_assign( int level, int precision )
{
bstring *s, *d;
/* Make sure the position one level below is a variable */
if ( exp_es[ level - 1 ].operation != VARIABLE )
{
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "in op_assign(): Assignment must be to variable: level -1 <%d> op <%d>",
level - 1, exp_es[ level - 1 ].operation );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return FALSE;
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_assign(): entered function level <%d>",
level );
bwb_debug( bwb_ebuf );
#endif
/* if the assignment is numerical, then the precision should be set
to that of the variable on the left-hand side of the assignment */
if ( precision != STRING )
{
precision = (int) exp_es[ level - 1 ].type;
}
switch( precision )
{
case STRING:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_assign(): try exp_getsval(), level <%d> op <%d> type <%c>:",
level - 1, exp_es[ level - 1 ].operation, exp_es[ level - 1 ].type );
bwb_debug( bwb_ebuf );
exp_getsval( &( exp_es[ level - 1 ] ));
sprintf( bwb_ebuf, "in op_assign(): try exp_getsval(), level <%d> op <%d> type <%c>:",
level + 1, exp_es[ level + 1 ].operation, exp_es[ level + 1 ].type );
bwb_debug( bwb_ebuf );
exp_getsval( &( exp_es[ level + 1 ] ));
sprintf( bwb_ebuf, "in op_assign(): string addition, exp_getsval()s completed" );
bwb_debug( bwb_ebuf );
#endif
str_btob( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) );
break;
case DOUBLE:
* var_finddval( exp_es[ level - 1 ].xvar,
exp_es[ level - 1 ].xvar->array_pos ) =
exp_es[ level - 1 ].dval =
exp_getdval( &( exp_es[ level + 1 ] ) );
break;
case SINGLE:
* var_findfval( exp_es[ level - 1 ].xvar,
exp_es[ level - 1 ].xvar->array_pos ) =
exp_es[ level - 1 ].fval =
exp_getfval( &( exp_es[ level + 1 ] ) );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_assign(): SINGLE assignment var <%s> val <%f>",
exp_es[ level - 1 ].xvar->name, exp_getfval( &( exp_es[ level - 1 ] )) );
bwb_debug( bwb_ebuf );
#endif
break;
case INTEGER:
* var_findival( exp_es[ level - 1 ].xvar,
exp_es[ level - 1 ].xvar->array_pos ) =
exp_es[ level - 1 ].ival =
exp_getival( &( exp_es[ level + 1 ] ) );
break;
default:
#if PROG_ERRORS
sprintf( bwb_ebuf, "in op_assign(): Variable before assignment operator has unidentified type." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
return FALSE;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_equals()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if they are the same
and FALSE if they are not.
***************************************************************/
static int
op_equals( int level, int precision )
{
int error_condition;
bstring b;
bstring *bp;
error_condition = FALSE;
b.rab = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be strings for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "in op_equals(): Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
bp = exp_getsval( &( exp_es[ level - 1 ] ));
b.length = bp->length;
b.buffer = bp->buffer;
if ( str_cmp( &b,
exp_getsval( &( exp_es[ level + 1 ] )) ) == 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
== exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
== exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
== exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_lessthan()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if the left hand value
is less than the right, and FALSE if it is not.
***************************************************************/
static int
op_lessthan( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
if ( str_cmp( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) ) < 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
< exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
< exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
< exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_greaterthan()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if the left hand value
is greater than the right, and FALSE if it is not.
***************************************************************/
static int
op_greaterthan( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
if ( str_cmp( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) ) > 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
> exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
> exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
> exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_lteq()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if the left hand value
is less than or equal to the right, and FALSE if it is not.
***************************************************************/
static int
op_lteq( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
if ( str_cmp( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) ) <= 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
<= exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
<= exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
<= exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_gteq()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if the left hand value
is greater than or equal to the right, and FALSE if
it is not.
***************************************************************/
static int
op_gteq( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
if ( str_cmp( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) ) >= 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
>= exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
>= exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
>= exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_notequal()
DESCRIPTION: This function compares two values and
returns an integer value: TRUE if they are not the
same and FALSE if they are.
***************************************************************/
static int
op_notequal( int level, int precision )
{
int error_condition;
error_condition = FALSE;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
if ( ( op_islevelstr( level - 1 ) != TRUE )
|| ( op_islevelstr( level + 1 ) != TRUE ) )
{
#if PROG_ERRORS
sprintf( bwb_ebuf, "Type mismatch in string comparison." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
error_condition = TRUE;
}
/* compare the two strings */
if ( error_condition == FALSE )
{
if ( str_cmp( exp_getsval( &( exp_es[ level - 1 ] )),
exp_getsval( &( exp_es[ level + 1 ] )) ) != 0 )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
}
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level - 1 ] ))
!= exp_getdval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level - 1 ] ))
!= exp_getfval( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level - 1 ] ))
!= exp_getival( &( exp_es[ level + 1 ] )) )
{
exp_es[ level - 1 ].ival = TRUE;
}
else
{
exp_es[ level - 1 ].ival = FALSE;
}
break;
}
/* set variable to integer and operation to NUMBER:
this must be done at the end, since at the beginning it
might cause op_islevelstr() to return a false error */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_modulus()
DESCRIPTION: This function divides the number on
the left by the number on the right and return the
remainder.
***************************************************************/
static int
op_modulus( int level, int precision )
{
static double iportion;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be divided." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
break;
case DOUBLE:
if ( exp_getdval( &( exp_es[ level + 1 ] ))
== 0.0 )
{
exp_es[ level - 1 ].dval = -1.0;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
/ exp_getdval( &( exp_es[ level + 1 ] ));
modf( exp_es[ level ].dval, &iportion );
exp_es[ level - 1 ].dval
= exp_getdval( &( exp_es[ level - 1 ] ))
- ( exp_getdval( &( exp_es[ level + 1 ] ))
* iportion );
break;
case SINGLE:
if ( exp_getfval( &( exp_es[ level + 1 ] ))
== (float) 0.0 )
{
exp_es[ level - 1 ].fval = (float) -1.0;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
/ exp_getfval( &( exp_es[ level + 1 ] ));
modf( (double) exp_es[ level ].fval, &iportion );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_modulus(): integer portion is %f",
iportion );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level - 1 ].fval
= exp_getfval( &( exp_es[ level - 1 ] ))
- ( exp_getfval( &( exp_es[ level + 1 ] ))
* (float) iportion );
break;
case INTEGER:
if ( exp_getival( &( exp_es[ level + 1 ] ))
== 0 )
{
exp_es[ level - 1 ].ival = -1;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
% exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_exponent()
DESCRIPTION: This function divides the number on
the left by the number on the right and return the
remainder.
***************************************************************/
static int
op_exponent( int level, int precision )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_exponent(): entered function level <%d>.",
level );
bwb_debug ( bwb_ebuf );
#endif
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be taken as exponents." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].dval
= pow( exp_getdval( &( exp_es[ level - 1 ] )),
exp_getdval( &( exp_es[ level + 1 ] )) );
break;
case SINGLE:
exp_es[ level - 1 ].fval
= (float) pow( exp_getdval( &( exp_es[ level - 1 ] )),
exp_getdval( &( exp_es[ level + 1 ] )) );
break;
case INTEGER:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_exponent(): Integer precision." );
bwb_debug ( bwb_ebuf );
sprintf( bwb_ebuf, "in op_exponent(): lhs <%f> rhs <%f>.",
exp_getdval( &( exp_es[ level - 1 ] )),
exp_getdval( &( exp_es[ level + 1 ] )) );
bwb_debug ( bwb_ebuf );
#endif
exp_es[ level - 1 ].ival
= (int) pow( exp_getdval( &( exp_es[ level - 1 ] )),
exp_getdval( &( exp_es[ level + 1 ] )) );
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = (char) precision;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_intdiv()
DESCRIPTION: This function divides the number on
the left by the number on the right and returns the
result as an integer.
***************************************************************/
static int
op_intdiv( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
string addition; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be divided." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
default:
if ( exp_getival( &( exp_es[ level + 1 ] ))
== 0 )
{
exp_es[ level - 1 ].ival = -1;
op_pulldown( 2 );
#if PROG_ERRORS
sprintf( bwb_ebuf, "Divide by 0." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_dbz );
#endif
return FALSE;
}
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_intdiv(): <%d> / <%d>",
exp_getival( &( exp_es[ level - 1 ] )),
exp_getival( &( exp_es[ level + 1 ] )) );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
/ exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable to requested precision */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_or()
DESCRIPTION: This function compares two integers and
performs a logical NOT on them, returning the result
as an integer.
***************************************************************/
static int
op_or( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
logical comparison; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be compared logically." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
| exp_getival( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
| exp_getival( &( exp_es[ level + 1 ] ));
break;
case INTEGER:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
| exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable type to integer */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_and()
DESCRIPTION: This function compares two integers and
performs a logical NOT on them, returning the result
as an integer.
***************************************************************/
static int
op_and( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
logical comparison; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be compared logically." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
& exp_getival( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
& exp_getival( &( exp_es[ level + 1 ] ));
break;
case INTEGER:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
& exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable type to integer */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_not()
DESCRIPTION: This function compares two integers and
performs a logical NOT on them, returning the result
as an integer.
***************************************************************/
static int
op_not( int level, int precision )
{
unsigned char r;
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
logical comparison; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be compared logically." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
default:
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_not(): argument is <%d>, precision <%c>",
(unsigned int) exp_getival( &( exp_es[ level + 1 ] )), precision );
bwb_debug( bwb_ebuf );
#endif
exp_es[ level ].ival =
~( exp_getival( &( exp_es[ level + 1 ] )) );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_not(): result is <%d>, precision <%c>",
(int) r, precision );
bwb_debug( bwb_ebuf );
#endif
break;
}
/* set variable type to integer */
exp_es[ level ].type = INTEGER;
exp_es[ level ].operation = NUMBER;
/* decrement the stack once */
op_pulldown( 1 );
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_not(): exp_esc <%d>, level <%d> result <%d>",
exp_esc, level, exp_es[ exp_esc ].ival );
bwb_debug( bwb_ebuf );
#endif
return TRUE;
}
/***************************************************************
FUNCTION: op_xor()
DESCRIPTION: This function compares two integers and
performs a logical NOT on them, returning the result
as an integer.
***************************************************************/
static int
op_xor( int level, int precision )
{
switch( precision )
{
case STRING:
/* both sides of the operation should be numbers for
logical comparison; if not, report an error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "Strings cannot be compared logically." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_mismatch );
#endif
break;
case DOUBLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
^ exp_getival( &( exp_es[ level + 1 ] ));
break;
case SINGLE:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
^ exp_getival( &( exp_es[ level + 1 ] ));
break;
case INTEGER:
exp_es[ level - 1 ].ival
= exp_getival( &( exp_es[ level - 1 ] ))
^ exp_getival( &( exp_es[ level + 1 ] ));
break;
}
/* set variable type to integer */
exp_es[ level - 1 ].type = INTEGER;
exp_es[ level - 1 ].operation = NUMBER;
/* decrement the stack twice */
op_pulldown( 2 );
return TRUE;
}
/***************************************************************
FUNCTION: op_islevelstr()
DESCRIPTION: This function determines whether the
operation at a specified level involves a string
constant or variable.
***************************************************************/
static int
op_islevelstr( int level )
{
/* first see if the level holds a string constant */
if ( exp_es[ level ].operation == CONST_STRING )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_islevelstr(): string detected at level <%d>.",
level );
bwb_debug( bwb_ebuf );
#endif
return TRUE;
}
/* see if the level holds a string variable */
if ( exp_es[ level ].operation == VARIABLE )
{
if ( exp_es[ level ].xvar->type == STRING )
{
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_islevelstr(): string detected at level <%d>.",
level );
bwb_debug( bwb_ebuf );
#endif
return TRUE;
}
}
/* test has failed, return FALSE */
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_islevelstr(): string not detected at level <%d>.",
level );
bwb_debug( bwb_ebuf );
#endif
return FALSE;
}
/***************************************************************
FUNCTION: op_getprecision()
DESCRIPTION: This function finds the precision for
an operation by comparing the precision at this level
and that two levels below.
***************************************************************/
static int
op_getprecision( int level )
{
/* first test for string value */
if ( ( exp_es[ level + 1 ].type == STRING )
|| ( exp_es[ level - 1 ].type == STRING ) )
{
return STRING;
}
/* Both are numbers, so we should be able to find a suitable
precision level by starting with the top and moving down;
check first for double precision */
if ( ( exp_es[ level + 1 ].type == DOUBLE )
|| ( exp_es[ level - 1 ].type == DOUBLE ) )
{
return DOUBLE;
}
/* check next for single precision */
if ( ( exp_es[ level + 1 ].type == SINGLE )
|| ( exp_es[ level - 1 ].type == SINGLE ) )
{
return SINGLE;
}
/* test integer precision */
if ( ( exp_es[ level + 1 ].type == INTEGER )
&& ( exp_es[ level - 1 ].type == INTEGER ) )
{
return INTEGER;
}
/* else error */
#if PROG_ERRORS
sprintf( bwb_ebuf, "in op_getprecision(): invalid precision level." );
bwb_error( bwb_ebuf );
#else
bwb_error( err_syntax );
#endif
return FALSE;
}
/***************************************************************
FUNCTION: op_pulldown()
DESCRIPTION: This function pulls the expression stack
down a specified number of levels, decrementing the
expression stack counter (bycalling dec_esc()) and
decrementing the current "level" of operation processing.
***************************************************************/
static int
op_pulldown( int how_far )
{
int level;
register int c;
#if INTENSIVE_DEBUG
sprintf( bwb_ebuf, "in op_pulldown(): pull down e stack <%d> place(s)",
how_far );
bwb_debug( bwb_ebuf );
#endif
/* first pull down the actual variables themselves */
level = op_level + ( 2 - how_far );
while ( exp_esc >= ( level + how_far ) )
{
memcpy( &exp_es[ level ], &exp_es[ level + how_far ],
(size_t) ( sizeof( struct exp_ese )) );
++level;
}
/* decrement the expression stack counter */
for ( c = 0; c < how_far; ++c )
{
if ( dec_esc() == TRUE )
{
--op_level;
}
else
{
return FALSE;
}
}
return TRUE;
}